#include "qlibc_log.h"
#include "utils_crc16.h"

static const unsigned short crc16_table[16] =
{
    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
    0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef
};

/**
 * @brief  计算CRC16校验，初值0xFFFF  polynomial: 0x11021
 * @param  pdata            需要计算CRC16的数据串指针
 * @param  len              数据长度
 * @return uint16_t CRC16校验值
 */
uint16_t stdlib_get_crc16(void *pdata, uint32_t len)
{
    uint16_t crc = 0;
    uint8_t *buf = (uint8_t *)pdata;
    uint8_t tmp;

    while (len--) {
        tmp = crc >> 12; /*取出高4位 ---------------*/
        crc <<= 4;       /*取出CRC的低12位) --------*/
        /*CRC的高4位和本字节的前半字节相加后查表计算CRC，然后加上上一次CRC的余数*/
        crc ^= crc16_table[tmp ^ (*buf >> 4)];
        tmp = crc >> 12;
        crc <<= 4;
        crc ^= crc16_table[tmp ^ (*buf & 0x0f)];
        buf++;
    }

    return crc;
}


/**
 * @brief ymodem CRC16 
 * @param  buf              My Param doc
 * @param  count            My Param doc
 * @return unsigned short 
 */
unsigned short stdlib_get_crc16_xmodem(const unsigned char *buf, unsigned int count)
{
    unsigned short crc = 0;
    int i;

    while(count--) {
        crc = crc ^ *buf++ << 8;

        for (i = 0; i < 8; i++) {
            if (crc & 0x8000) {
                crc = crc << 1 ^ 0x1021;
            } else {
                crc = crc << 1;
            }
        }
    }
    return crc;
}